package org.kabeja.dxf;

import org.kabeja.dxf.entity.*;
import org.kabeja.dxf.objects.DXFDictionary;
import org.kabeja.dxf.objects.DXFObject;

import java.util.*;

/**
 * @author shutao
 * @since 2022/4/24 16:46
 */
public class DXFDocument {
    public static String PROPERTY_ENCODING = "encoding";
    public static final double DEFAULT_MARGIN = 5.0D;
    private final Map<String, DXFLayer> layers = new HashMap<>();
    private final Map<String, DXFBlock> blocks = new HashMap<>();
    private final List<DXFEntity> entities = new ArrayList<>();
    private final Map<String, DXFLineType> lineTypes = new HashMap<>();
    private final Map<String, DXFDimensionStyle> dimensionStyles = new HashMap<>();
    private final Map<String, DXFStyle> textStyles = new HashMap<>();
    private final Map<String, String> properties = new HashMap<>();
    private final List<Object> viewports = new ArrayList<>();
    private Bounds bounds = new Bounds();
    private DXFHeader header = new DXFHeader();
    private final Map<String, Map<String, DXFObject>> objects = new HashMap<>();
    private final Map<String, DXFHatchPattern> patterns = new HashMap<>();
    private final List<DXFView> views = new ArrayList<>();
    private DXFDictionary rootDictionary = new DXFDictionary();

    public DXFDocument() {
        DXFLayer var1 = new DXFLayer();
        var1.setDXFDocument(this);
        var1.setName("0");
        this.layers.put("0", var1);
        this.rootDictionary = new DXFDictionary();
        this.rootDictionary.setDXFDocument(this);
    }

    public void addDXFLayer(DXFLayer var1) {
        var1.setDXFDocument(this);
        this.layers.put(var1.getName(), var1);
    }

    public DXFLayer getDXFLayer(String var1) {
        if (this.layers.containsKey(var1)) {
            return this.layers.get(var1);
        } else if (this.layers.containsKey("0")) {
            return this.layers.get("0");
        } else {
            DXFLayer var2 = new DXFLayer();
            var2.setName("0");
            this.addDXFLayer(var2);
            return var2;
        }
    }

    public boolean containsDXFLayer(String var1) {
        return this.layers.containsKey(var1);
    }

    public Iterator<DXFLayer> getDXFLayerIterator() {
        return this.layers.values().iterator();
    }

    public void addDXFLineType(DXFLineType var1) {
        this.lineTypes.put(var1.getName(), var1);
    }

    public DXFLineType getDXFLineType(String var1) {
        return this.lineTypes.get(var1);
    }

    public Iterator<?> getDXFLineTypeIterator() {
        return this.lineTypes.values().iterator();
    }

    public void addDXFEntity(DXFEntity var1) {
        var1.setDXFDocument(this);
        DXFLayer var2 = this.getDXFLayer(var1.getLayerName());
        var2.addDXFEntity(var1);
        this.entities.add(var1);
    }

    public List<DXFEntity> getEntities() {
        return this.entities;
    }

    public void addDXFBlock(DXFBlock var1) {
        var1.setDXFDocument(this);
        this.blocks.put(var1.getName(), var1);
    }

    public DXFBlock getDXFBlock(String var1) {
        return this.blocks.get(var1);
    }

    public Map<String, DXFBlock> getBlocks() {
        return this.blocks;
    }

    public Iterator<DXFBlock> getDXFBlockIterator() {
        return this.blocks.values().iterator();
    }

    public void setProperty(String var1, String var2) {
        this.properties.put(var1, var2);
    }

    public String getProperty(String var1) {
        return this.properties.getOrDefault(var1, null);
    }

    public boolean hasProperty(String var1) {
        return this.properties.containsKey(var1);
    }

    public Bounds getBounds() {
        this.bounds = new Bounds();
        this.layers.forEach((key, value) -> {
            if (!value.isFrozen()) {
                Bounds var3 = value.getBounds();
                if (var3.isValid()) {
                    this.bounds.addToBounds(var3);
                }
            }
        });

        return this.bounds;
    }

    public Bounds getBounds(boolean var1) {
        Bounds var2 = new Bounds();

        this.layers.forEach((key, value) -> {
            if (!value.isFrozen()) {
                Bounds var3 = value.getBounds(var1);
                if (var3.isValid()) {
                    var2.addToBounds(var3);
                }
            }
        });

        return var2;
    }

    /** @deprecated */
    public double getHeight() {
        return this.bounds.getHeight();
    }

    /** @deprecated */
    public double getWidth() {
        return this.bounds.getWidth();
    }

    public DXFHeader getDXFHeader() {
        return this.header;
    }

    public void setDXFHeader(DXFHeader var1) {
        this.header = var1;
    }

    public void addDXFDimensionStyle(DXFDimensionStyle var1) {
        this.dimensionStyles.put(var1.getName(), var1);
    }

    public DXFDimensionStyle getDXFDimensionStyle(String var1) {
        return this.dimensionStyles.get(var1);
    }

    public Iterator<DXFDimensionStyle> getDXFDimensionStyleIterator() {
        return this.dimensionStyles.values().iterator();
    }

    public void addDXStyle(DXFStyle var1) {
        this.textStyles.put(var1.getName(), var1);
    }

    public DXFStyle getDXFStyle(String var1) {
        return this.textStyles.get(var1);
    }

    public Map<String, DXFStyle> getTextStyleMaps() {
        return this.textStyles;
    }

    public Iterator<DXFStyle> getDXFStyleIterator() {
        return this.textStyles.values().iterator();
    }

    public void removeDXFLayer(String var1) {
        this.layers.remove(var1);
    }

    public void addDXFViewport(DXFViewport var1) {
        this.viewports.add(var1);
    }

    public Iterator<?> getDXFViewportIterator() {
        return this.viewports.iterator();
    }

    public void removeDXFViewport(DXFViewport var1) {
        this.viewports.remove(var1);
    }

    public void removeDXFViewport(int var1) {
        this.viewports.remove(var1);
    }

    public void addDXFView(DXFView var1) {
        this.views.add(var1);
    }

    public Iterator<DXFView> getDXFViewIterator() {
        return this.views.iterator();
    }

    public void addDXFObject(DXFObject var1) {
        DXFDictionary var2 = this.rootDictionary.getDXFDictionaryForID(var1.getID());
        if (var2 != null) {
            var2.putDXFObject(var1);
        } else {
            Map<String, DXFObject> var3 = null;
            if (this.objects.containsKey(var1.getObjectType())) {
                var3 = this.objects.get(var1.getObjectType());
            } else {
                var3 = new HashMap<>();
                this.objects.put(var1.getObjectType(), var3);
            }

            var3.put(var1.getID(), var1);
        }

    }

    public DXFDictionary getRootDXFDictionary() {
        return this.rootDictionary;
    }

    public void setRootDXFDictionary(DXFDictionary var1) {
        this.rootDictionary = var1;
    }

    public List<DXFObject> getDXFObjectsByType(String var1) {
        Map<String, DXFObject> var2 = this.objects.get(var1);
        return new ArrayList<>(var2.values());
    }

    public DXFObject getDXFObjectByID(String var1) {
        Iterator<Map<String, DXFObject>> var2 = this.objects.values().iterator();

        Map<String, DXFObject> var3;
        DXFObject var4;
        do {
            if (!var2.hasNext()) {
                return this.rootDictionary.getDXFObjectByID(var1);
            }

            var3 = var2.next();
        } while((var4 = var3.get(var1)) == null);

        return var4;
    }

    public DXFEntity getDXFEntityByID(String var1) {
        DXFEntity var2 = null;
        Iterator<?> var3 = this.getDXFLayerIterator();

        DXFLayer var4;
        do {
            if (!var3.hasNext()) {
                var3 = this.getDXFBlockIterator();

                DXFBlock var5;
                do {
                    if (!var3.hasNext()) {
                        return var2;
                    }

                    var5 = (DXFBlock)var3.next();
                } while((var2 = var5.getDXFEntityByID(var1)) == null);

                return var2;
            }

            var4 = (DXFLayer)var3.next();
        } while((var2 = var4.getDXFEntityByID(var1)) == null);

        return var2;
    }

    public void addDXFHatchPattern(DXFHatchPattern var1) {
        this.patterns.put(var1.getID(), var1);
    }

    public Iterator<DXFHatchPattern> getDXFHatchPatternIterator() {
        return this.patterns.values().iterator();
    }

    public DXFHatchPattern getDXFHatchPattern(String var1) {
        return this.patterns.get(var1);
    }
}
